<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Eidos Script Container</title>
    <script type="module">
      const makeSpaceProxy = (space) => {
        return new Proxy(
          {},
          {
            get: (target, method) => {
              const msgChannel = new MessageChannel()
              const send = (data) => {
                window.parent.postMessage(
                  {
                    type: "rpcCall",
                    data,
                  },
                  "*",
                  [msgChannel.port2]
                )
              }
              const onCallBack = () => {
                return new Promise((resolve, reject) => {
                  msgChannel.port1.onmessage = (event) => {
                    msgChannel.port1.close()
                    const { type, data } = event.data
                    if (type === "rpcCallResp") {
                      resolve(data)
                    }
                  }
                })
              }

              // const r = await currentSpace.table("91ba4dd2ad4447cf943db88dbb861323").rows.query()
              if (method == "table") {
                return function (id) {
                  return new Proxy(
                    {},
                    {
                      get(target, method) {
                        if (method == "rows") {
                          return new Proxy(
                            {},
                            {
                              get(target, method) {
                                return function (params) {
                                  const [_params, ...rest] = arguments
                                  send({
                                    method: `table(${id}).rows.${method}`,
                                    params: [_params, ...rest],
                                    space,
                                  })
                                  return onCallBack()
                                }
                              },
                            }
                          )
                        }
                        return function (params) {
                          const [_params, ...rest] = arguments
                          send({
                            method: `table("${id}").${method}`,
                            params: [_params, ...rest],
                            space,
                          })
                          return onCallBack()
                        }
                      },
                    }
                  )
                }
              }
              if (
                [
                  "doc",
                  "action",
                  "script",
                  "tree",
                  "view",
                  "column",
                  "embedding",
                  "file",
                ].includes(method)
              ) {
                return new Proxy(
                  {},
                  {
                    get(target, subMethod) {
                      return function (params) {
                        const [_params, ...rest] = arguments
                        send({
                          method: `${method}.${subMethod}`,
                          params: [_params, ...rest],
                          space,
                        })
                        return onCallBack()
                      }
                    },
                  }
                )
              }

              return (...params) => {
                send({
                  space,
                  method,
                  params,
                })
                return onCallBack()
              }
            },
          }
        )
      }

      window.eidos = new Proxy(
        {},
        {
          get: (target, prop) => {
            if (prop === "space") {
              // eidos.space(spaceId)
              return (space) => {
                return makeSpaceProxy(space)
              }
            }
            if (prop === "currentSpace") {
              return makeSpaceProxy("${{currentSpace}}")
            }
          },
        }
      )

      let modules = {}
      async function loadScriptFunction(code) {
        const blob = new Blob([code], { type: "text/javascript" })
        const url = URL.createObjectURL(blob)
        const module = await import(url)
        return module
      }
      window.addEventListener("message", async (event) => {
        const { type, data } = event.data
        const port = event.ports[0]
        if (type === "ScriptFunctionCall") {
          const { input, context, code, command } = data
          try {
            const module = await loadScriptFunction(code)
            const res = await module[command](input, context)
            port.postMessage({
              type: "ScriptFunctionCallResponse",
              data: res,
            })
          } catch (error) {
            port.postMessage({
              type: "ScriptFunctionCallError",
              data: error,
            })
          }
        }
      })
    </script>
  </head>
  <body>
    <p id="message">Loading...</p>
  </body>
</html>
